package cn.cdeden.knowledge.controller.recycle.factory;

import cn.cdeden.common.core.domain.R;
import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.core.utils.page.TableDataInfo;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.EnterpriseFilesTree;
import cn.cdeden.knowledge.domain.FilesTreeRecycle;
import cn.cdeden.knowledge.domain.dto.FileUserDto;
import cn.cdeden.knowledge.domain.dto.FilesTreeRecycleParam;
import cn.cdeden.knowledge.domain.dto.SysMessageDto;
import cn.cdeden.knowledge.domain.dto.TreeNodeDto;
import cn.cdeden.knowledge.domain.enums.MessageTypeEnums;
import cn.cdeden.knowledge.domain.vo.FilesTreeRecycleVo;
import cn.cdeden.knowledge.enums.DeleteTypeEnums;
import cn.cdeden.knowledge.enums.MessageFileTypeEnums;
import cn.cdeden.knowledge.enums.TreeEnum;
import cn.cdeden.knowledge.enums.TreeTypeEnum;
import cn.cdeden.knowledge.mapper.EnterpriseFilesTreeMapper;
import cn.cdeden.knowledge.service.*;
import cn.cdeden.knowledge.utils.PageUtil;
import cn.cdeden.system.api.domain.enums.EnterprisePermTypeEnum;
import cn.cdeden.system.api.model.LoginUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.undertow.util.BadRequestException;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Component("enterpriseRecycle")
public class RecycleEnterprise implements RecycleInterface {

//    @DubboReference(check = false)
    private final EnterprisePermService enterprisePermService;

    private final EnterpriseFilesTreeService enterpriseFilesTreeService;

    private final FilesCollectionService filesCollectionService;

    private final FilesLabelRecordService filesLabelRecordService;

    private final FilesTreeService filesTreeService;

    private final FilesAttentionService filesAttentionService;

    private final EnterpriseFilesTreeMapper treeMapper;

    private final SysMessageService messageService;


    @Override
    public boolean deleteBatch(List<String> ids, String info) throws BadRequestException {
        //验证删除权限
        List<String> realNames = new ArrayList<>();
        String str = "";
//        FileUserDto user;

        LoginUser user = LoginHelper.getLoginUser();
//        user = FileUserUtils.getUser();

        for (int i = 0; i < ids.size(); i++) {
            if (enterprisePermService.checkPermission(Long.valueOf(ids.get(i)), EnterprisePermTypeEnum.EDITOR,user.getUserId())) {
//            if (enterprisePermService.checkPermission(Long.valueOf(ids.get(i)), EnterprisePermTypeEnum.EDITOR,user.getUserId())) {
                EnterpriseFilesTree enterpriseFilesTree = enterpriseFilesTreeService.getById(ids.get(i));
                realNames.add(enterpriseFilesTree.getRealName());
            }
        }
        if (realNames.size() > 0) {
            for (int i = 0; i < realNames.size(); i++) {
                if (i == realNames.size() - 1) {
                    str.concat(realNames.get(i) + "。");
                } else {
                    str.concat(realNames.get(i) + "、");
                }
            }
        }else {
            throw new BadRequestException("选择移动失败：" + str + " 无废除权限");
        }

        String username = user.getUsername();
        String userId = Long.toString(user.getUserId());
        List<EnterpriseFilesTree> treeList = enterpriseFilesTreeService.listByIds(ids);

        if (CollectionUtils.isEmpty(treeList)) {
            throw new BadRequestException("错误的信息删除");
        } else {
            treeList.forEach(filesTree -> {

                if (!enterprisePermService.checkPermission(filesTree.getId(),EnterprisePermTypeEnum.EDITOR,user.getUserId()))
//                if (!enterprisePermService.checkPermission(filesTree.getId(),EnterprisePermTypeEnum.EDITOR,user.getUserId()))
                    try {
                        throw new BadRequestException("没有删除权限");
                    } catch (BadRequestException e) {
                        e.printStackTrace();
                    }
                //修改所有上级文件大小
                enterpriseFilesTreeService.setParentNodeSize(filesTree.getParentId(), filesTree.getSize(), 1);
            });
            Set<String> setIds = new HashSet<>();
            setIds.addAll(deleteBatch(ids, userId, username));
            setIds.addAll(ids);
            List<String> list = new ArrayList<>(setIds);
            filesCollectionService.deleteLibTaggedData("2", list);
            filesLabelRecordService.deleteByFileIds(setIds, TreeEnum.ENTERPRISE.getType());
            UpdateWrapper<EnterpriseFilesTree> updateWrapper = new UpdateWrapper<EnterpriseFilesTree>()
                .set("delete_id", userId).set("delete_by", username)
                .set("delete_type", DeleteTypeEnums.DISPLAY.getType())
                .set("delete_time", new Date())
                .in("id", ids);

            for (String setId : setIds) {
                EnterpriseFilesTree enterpriseFilesTree = enterpriseFilesTreeService.getById(setId);
                List<TreeNodeDto> parentTreeNodeAll = filesTreeService.getParentTreeNodeAll(String.valueOf(enterpriseFilesTree.getId()), "2");
                for (int i = 0; i < parentTreeNodeAll.size(); i++) {
                    String id = parentTreeNodeAll.get(i).getId();
                    List<String> attentionPeople = filesAttentionService.getAttentionPeople(id, "2");
                    for (int j = 0; j < attentionPeople.size(); j++) {
                        //创建消息
                        SysMessageDto sysMessageDto = new SysMessageDto();
                        sysMessageDto.setContent("您关注的文件夹/文件名为“"+parentTreeNodeAll.get(i).getRealName()+"”,已被用户昵称为“"+user.getNickname()+"”删除");
                        sysMessageDto.setOperator(user.getUserId().toString());
                        sysMessageDto.setNodeId(parentTreeNodeAll.get(i).getId().toString());
                        sysMessageDto.setMessageType("0");
                        sysMessageDto.setType(MessageTypeEnums.DELETE.getCode());
                        sysMessageDto.setFileType(MessageFileTypeEnums.ENTERPRISE.getCode());
                        sysMessageDto.setRecipient(attentionPeople.get(j));
                        sysMessageDto.setTeamId(String.valueOf(enterpriseFilesTree.getLibraryId()));
                        messageService.addMessage(sysMessageDto);
                    }
                    //获取企业文件子文件的关注人
/*
                    List<String> childAllById = enterpriseFilesTreeService.getChildAllById(id);
                    for (String childId : childAllById) {
                        EnterpriseFilesTree childEnterpriseFilesTree = enterpriseFilesTreeService.getById(childId);
                        List<String> childAttentionPeople = filesAttentionService.getAttentionPeople(childId,"2");
                        for (String childAttentionPerson : childAttentionPeople) {
                           SysMessageDto sysMessageDto = new SysMessageDto();
                            sysMessageDto.setContent("您关注的文件/文件夹“"+childEnterpriseFilesTree.getRealName()+"”,已被用户昵称为“"+user.getNickname()+"”删除");
                            sysMessageDto.setOperator(user.getUserId().toString());
                            sysMessageDto.setNodeId(childEnterpriseFilesTree.getId().toString());
                            sysMessageDto.setMessageType("0");
                            sysMessageDto.setType(TreeEnum.ENTERPRISE.getType());
                            sysMessageDto.setRecipient(childAttentionPerson);
                            messageService.addMessage(sysMessageDto);
                       }
                    }
*/
                }
                //TODO 加入日志
//                sysDocLogService.createLog(setId,user,TreeEnum.ENTERPRISE, OperationEnum.DELETE.getOperation(OperationEnum.OperationTypeEnum.Document),enterpriseFilesTree.getRealName(),enterpriseFilesTree.getPath(),enterpriseFilesTree.getDeleteType());
            }
            return enterpriseFilesTreeService.update(updateWrapper);
        }
    }

    @Override
    public TableDataInfo<FilesTreeRecycleVo> selectRecycleAll(FilesTreeRecycleParam query, Pageable pageable) {
        IPage<EnterpriseFilesTree> page = PageUtil.toMybatisPage(pageable);
        List<String> sortDesc = query.getSortDesc();
        List<String> sortAsc = query.getSortAsc();
//        FileUserDto user = FileUserUtils.getUser(); //用户信息
        LoginUser user = LoginHelper.getLoginUser();
        String username = user.getUsername();
        String userId = Long.toString(user.getUserId());

        if (CollectionUtils.isEmpty(sortDesc) && CollectionUtils.isEmpty(sortAsc)) {
            sortDesc = new ArrayList<>();
            sortDesc.add("delete_time");
        }

        QueryWrapper<EnterpriseFilesTree> predicate = QueryHelpMybatisPlus.getPredicate(query);

        predicate.eq("library_id",query.getLibraryId());
        predicate.orderByDesc("delete_time").eq("delete_type", "1");

        IPage<EnterpriseFilesTree> pageList = treeMapper.selectPage(page, predicate);
        TableDataInfo<EnterpriseFilesTree> build = TableDataInfo.build(pageList);

//        List<EnterpriseFilesTree> records = pageList.getRecords();
//        List<FilesTreeRecycleVo> treeVoList = ConvertUtil.convertList(records, FilesTreeRecycleVo.class);
        return MapstructUtils.convertTableDataInfo(build, FilesTreeRecycleVo.class);
    }

    @Override
    public List<FilesTreeRecycle> deleteRecycle(List<String> ids, String type, String teamId) throws BadRequestException {
//        if (!enterprisePermService.isEnterpriseAdminOrAdmin(null)) throw new BadRequestException("企业文档管理员才可操作");
        List<FilesTreeRecycle> recycleList = null;
        List<String> list = new ArrayList<>();
        if (StringUtils.equalsIgnoreCase("0", type)) {
            if (CollectionUtils.isEmpty(ids)) {
                throw new BadRequestException("删除数据为空");
            }
            recycleList = deleteRecycle(ids);

        } else if (StringUtils.equalsIgnoreCase("1", type) && !StringUtils.isEmpty(teamId)) {
            recycleList = deleteRecycleAll(teamId);
        }

//        recycleList.forEach(FilesTreeRecycle::getFileTreeId);
//        //删除数据

        if (CollectionUtils.isEmpty(recycleList)) {
            throw new BadRequestException("删除数据为空");
        }
        List<Long> longs = recycleList.stream().map(FilesTreeRecycle::getFileTreeId).collect(Collectors.toList());
        boolean b = enterpriseFilesTreeService.removeByIds(longs);

        return recycleList;
    }

    private List<FilesTreeRecycle> deleteRecycle(List<String> ids) {
        LoginUser user = LoginHelper.getLoginUser();
        String username = user.getUsername();
        String userId = Long.toString(user.getUserId());

        if (CollectionUtils.isEmpty(ids)) {
            throw new RuntimeException("错误的 删除对象");
        }

        QueryWrapper<EnterpriseFilesTree> wrapper = new QueryWrapper<EnterpriseFilesTree>()
            .eq("delete_id", userId)
            .eq("delete_type", "1")
            .in("id", ids);
        List<EnterpriseFilesTree> treeList = enterpriseFilesTreeService.list(wrapper);
        if (CollectionUtils.isEmpty(treeList)) {
            throw new RuntimeException("没有要删除的对象");
        }
        return deleteRecycleActual(userId, treeList);
    }

    @Override
    public R recoverFileList(List<String> ids, String teamId) {
//        if (!enterprisePermService.isEnterpriseAdminOrAdmin(null))throw new RuntimeException("企业文档管理员才可操作");
        if (ids.size() > 1) {
            return recoverFile(ids);
        } else {
            return recoverFile(ids.get(0));
        }
    }

    public R recoverFile(String id) {
        LoginUser user = LoginHelper.getLoginUser();
        String username = user.getUsername();
        String userId = Long.toString(user.getUserId());
        QueryWrapper<EnterpriseFilesTree> queryWrapper = new QueryWrapper<EnterpriseFilesTree>();
        queryWrapper.eq("id", id).isNotNull("delete_id");
        EnterpriseFilesTree filesTree = enterpriseFilesTreeService.getOne(queryWrapper);

        QueryWrapper<EnterpriseFilesTree> wrapper = new QueryWrapper<EnterpriseFilesTree>()
            .eq("id", filesTree.getParentId()).isNull("delete_id");

        EnterpriseFilesTree personalFile = enterpriseFilesTreeService.getOne(wrapper);
        if (ObjectUtils.isEmpty(personalFile)) {
            return R.fail( "请选择其他位置");
        }
        boolean b = recoverFile(filesTree, userId, username);
        return R.ok( "还原成功");
    }
    public R recoverFile(List<String> ids) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        String username = loginUser.getUsername();
        String userId = Long.toString(loginUser.getUserId());
        QueryWrapper<EnterpriseFilesTree> queryWrapper = new QueryWrapper<EnterpriseFilesTree>();
        queryWrapper.in("id", ids).isNotNull("delete_id");
        List<EnterpriseFilesTree> filesTrees = enterpriseFilesTreeService.list(queryWrapper);
        if (CollectionUtils.isEmpty(filesTrees) && filesTrees.size() != ids.size()) {
            throw new RuntimeException("错误的 有错误的 文件序号");
        }
        List<EnterpriseFilesTree> success = new ArrayList<>();
        List<EnterpriseFilesTree> exception = new ArrayList<>();
        // 循环恢复数据
        filesTrees.forEach(file -> {
            boolean b = recoverFile(file, userId, username);
            if (b) {
                success.add(file);
            } else {
                exception.add(file);
            }
        });

        if (CollectionUtils.isNotEmpty(exception) && exception.size() > 0) {
            StringBuilder message = new StringBuilder(success.size() + "个对象还原成功,");
            StringJoiner joiner = new StringJoiner(",");
            exception.forEach(tree -> {
                joiner.add(tree.getRealName());
            });
            message.append(joiner);
            message.append("等");
            message.append(exception.size());
            message.append("个对象的原目录文件夹已不存在，请单独进行还原");
            return R.fail(message.toString());
        } else {
            return R.ok("还原成功");
        }
    }
    public boolean recoverFile(EnterpriseFilesTree filesTree, String userId, String username) {
        QueryWrapper<EnterpriseFilesTree> queryWrapper = new QueryWrapper<EnterpriseFilesTree>()
            .eq("id", filesTree.getParentId()).isNull("delete_id");

        EnterpriseFilesTree personalFile = enterpriseFilesTreeService.getOne(queryWrapper);
        //修改上级文件大小
        Long filesTreeSize = filesTree.getSize() !=null ?  filesTree.getSize() : 0;
        Long personalFileSize =  personalFile.getSize() !=null ?   personalFile.getSize() : 0;

        personalFile.setSize(personalFileSize + filesTreeSize);
        enterpriseFilesTreeService.updateById(personalFile);
        if (ObjectUtils.isEmpty(personalFile)) {
            return false;
        }
        String realName = filesTree.getRealName();
        String id = Long.toString(filesTree.getId());
        if (enterpriseFilesTreeService.nameRechecking(realName, String.valueOf(filesTree.getParentId()), filesTree.getSuffix()) != null) {
            realName += "_" + System.currentTimeMillis();
        }

        //看是否是文件夹 下是否要恢复文件
        if (StringUtils.equalsIgnoreCase(TreeTypeEnum.FOLDER.getType(), filesTree.getType())) {
            recoverFile(Long.toString(filesTree.getId()), userId, username);
        }

        UpdateWrapper<EnterpriseFilesTree> updateWrapper = new UpdateWrapper<EnterpriseFilesTree>()
            .set("delete_id", null).set("delete_by", null)
            .set("delete_time", null)
            .set("delete_type", null)
            .set("real_name", realName)
            .set("update_id", userId).set("update_by", username).set("update_time", new Date())
            .eq("id", filesTree.getId());
        return enterpriseFilesTreeService.update(updateWrapper);
    }

    public boolean recoverFile(String id, String userId, String username) {
        QueryWrapper<EnterpriseFilesTree> queryWrapper = new QueryWrapper<EnterpriseFilesTree>()
            .eq("parent_id", id).isNotNull("delete_id").eq("delete_type", "2");
        List<EnterpriseFilesTree> treeList = enterpriseFilesTreeService.list(queryWrapper);
        if (CollectionUtils.isEmpty(treeList)) {
            return true;
        }

        Set<String> ids = new HashSet<>();
        List<String> idList = new ArrayList<>();
        treeList.forEach(tree -> {
            String of = String.valueOf(tree.getId());
            if (StringUtils.equalsIgnoreCase(TreeTypeEnum.FOLDER.getType(), tree.getType())) {
                idList.add(of);
            }
            ids.add(of);
        });

        //查找需要修改文件的
        folderCheck(idList, ids, false);

        UpdateWrapper<EnterpriseFilesTree> updateWrapper = new UpdateWrapper<EnterpriseFilesTree>()
            .set("delete_id", null).set("delete_by", null)
            .set("delete_time", null)
            .set("delete_type", null)
            .set("update_id", userId).set("update_by", username).set("update_time", new Date())
            .in("id", ids);
        return enterpriseFilesTreeService.update(updateWrapper);
    }
    private Set<String> deleteBatch(List<String> ids, String userId, String username) {
        QueryWrapper<EnterpriseFilesTree> queryWrapper = new QueryWrapper<EnterpriseFilesTree>().in("parent_id", ids).isNull("delete_id");
        List<EnterpriseFilesTree> list = enterpriseFilesTreeService.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            Set<String> setId = new HashSet<>();
            List<String> list1 = new ArrayList<>();
            list.forEach(tree -> {
                String of = String.valueOf(tree.getId());
                setId.add(of);
                if (StringUtils.equalsIgnoreCase(TreeTypeEnum.FOLDER.getType(), tree.getType())) {
                    list1.add(of);
                }
            });
            folderCheck(list1, setId, true);
//            throw new BadRequestException("选中的文件夹中有子级，无法删除");
//            setId.forEach(System.out::println);

            UpdateWrapper<EnterpriseFilesTree> updateWrapper = new UpdateWrapper<EnterpriseFilesTree>()
                .set("delete_id", userId).set("delete_by", username)
                .set("delete_type", DeleteTypeEnums.NO_DISPLAY.getType())
                .set("delete_time", new Date())
                .in("id", setId);
            enterpriseFilesTreeService.update(updateWrapper);
            return setId;
        }
        return new HashSet<>();
    }

    /**
     * @param ids
     * @param setId
     * @param b
     * @return void
     * @author Yu.
     * @Description // 文件下的所有文件
     * @Date 2022/10/14 15:51
     **/
    private void folderCheck(List<String> ids, Set<String> setId, boolean b) {
        if (CollectionUtils.isEmpty(ids) || ids.size() <= 0) {
            return;
        }
//        ArrayList<String> ids = new ArrayList<>(setId);
        QueryWrapper<EnterpriseFilesTree> queryWrapper = new QueryWrapper<EnterpriseFilesTree>().in("parent_id", ids);
        if (b) {
            queryWrapper.isNull("delete_id");
        } else {
            queryWrapper.isNotNull("delete_id").eq("delete_type", "2");
        }
        List<EnterpriseFilesTree> list = enterpriseFilesTreeService.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            List<String> list1 = new ArrayList<>();
            list.forEach(tree -> {
                if (StringUtils.equalsIgnoreCase(TreeTypeEnum.FOLDER.getType(), tree.getType())) {
                    list1.add(String.valueOf(tree.getId()));
                }
                setId.add(String.valueOf(tree.getId()));
            });
            folderCheck(list1, setId, b);
//            throw new BadRequestException("选中的文件夹中有子级，无法删除");
        }
    }

    private List<FilesTreeRecycle> deleteRecycleAll(String teamId) {
        LoginUser loginUser = LoginHelper.getLoginUser();

        String username = loginUser.getUsername();
        String userId = Long.toString(loginUser.getUserId());
        QueryWrapper<EnterpriseFilesTree> wrapper = new QueryWrapper<EnterpriseFilesTree>()
            .eq("delete_id", userId)
            .eq("library_id",teamId)
//                .eq("delete_type","1")
            ;
        List<EnterpriseFilesTree> treeList = enterpriseFilesTreeService.list(wrapper);
        if (CollectionUtils.isEmpty(treeList)) {
            throw new RuntimeException("没有要删除的对象");
        }
        return deleteRecycleActual(userId, treeList);
    }

    private List<FilesTreeRecycle> deleteRecycleActual(String userId, List<EnterpriseFilesTree> treeList) {
//        List<PersonalFilesTree> fileList = new ArrayList<>();
        List<FilesTreeRecycle> recycleList = new ArrayList<>();
        List<String> ids = new ArrayList<>();
        treeList.forEach(tree -> {
            FilesTreeRecycle recycle = FilesTreeRecycle.getEnterpriseRecycle(tree);
            if (StringUtils.equalsIgnoreCase(tree.getType(), TreeTypeEnum.FOLDER.getType())) {
//                ids.add(Long.toString(tree.getId()));
                Long treeId = recycle.getFileTreeId();
//                recycleList.add
                recycleList.add(recycle);
//                List<FilesTreeRecycle> treeRecycles = deleteRecycleActual(userId, String.valueOf(treeId), recycleList);
//                recycleList.addAll(treeRecycles);
            } else {
                recycleList.add(recycle);
            }
        });

//        //删除 文件树
//        filesTreeService.removeByIds(ids);
//
//        //删除 实际文件
//        if (CollectionUtils.isNotEmpty(fileList)) {
//            List<String> fileIds = new ArrayList<>();
//            List<String> Ids = new ArrayList<>();
//            fileList.forEach(tree -> {
//                fileIds.add(tree.getStorageId());
//                Ids.add(Long.toString(tree.getId()));
//            });
//            fileStorageUtils.deleteBatch(fileIds);
//            filesTreeService.removeByIds(Ids);
//        }
        return recycleList;
    }


}
